import time

from django.db import transaction
from ability.cloud import CloudImage, CloudInstance
from ability.serializer.image import TempInstancesSerializer
from ability.enums import ErrorCode
from rest_framework import mixins, viewsets
import traceback
from django.db.models.query_utils import Q
from ability.format import CustomResponse, GetPostParaOrNone
from ability.models import Image, TempInstance,Experiment,Environment
from ability.serializer.serializers import ImageListSerializer
from rest_framework.generics import ListAPIView
from rest_framework.response import Response
from rest_framework.views import APIView
from ability.excepts import LogicException
import ability.permissions as pm
from rest_framework import permissions
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
import logging
from study import proxmox_utils

from django.core.management.base import BaseCommand
from ability.models import  Image
from tencentcloud.cvm.v20170312 import models
from ability.cloud import client


logger = logging.getLogger(__name__)

class ImageListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = Image.objects.all()
    serializer_class = ImageListSerializer
    permission_classes = [pm.CustomIsAuthenticated, pm.AdminPermission|pm.TeacherPermission]

    def get_queryset(self):
        queryset = Image.objects.filter(status='N').order_by('-create_time')

        banned = [None,'']
        image_name = self.request.query_params.get('image_name', None)
        if image_name not in banned:
            queryset = queryset.filter(image_name__contains=image_name.strip())
        # 是否为获取公用镜像
        get_public = self.request.query_params.get('get_public', None)
        if get_public == '1':
            queryset = queryset.filter(owner_id=None)
            return queryset
        elif get_public == '2':
            queryset = queryset.filter(Q(status='N')).order_by('-create_time')
        else:
            if self.request.user.user_type != 'A':
                queryset = queryset.filter(Q(status='N'),Q(owner=self.request.user)).order_by('-create_time')
        # image_id = self.request.query_params.get('image_id', None)
        # image_type = self.request.query_params.get('image_type', None)
        # import_status = self.request.query_params.get('import_status', None)
        # if import_status not in banned:
        #     queryset = queryset.filter(import_status=import_status)
        # if image_id not in banned:
        #     queryset = queryset.filter(id=image_id)
        # if str(image_type) in ['1','2','3']:
        #     queryset = queryset.filter(image_type=trans.image_type[str(image_type)])
        # return queryset
                # image_id = self.request.query_params.get('image_id', None)
        id = self.request.query_params.get('id', None)
        image_type = self.request.query_params.get('image_type', None)
        import_status = self.request.query_params.get('import_status', None)
        experiment_name = self.request.query_params.get('experiment_name', None)
        if import_status not in banned:
            queryset = queryset.filter(import_status=import_status)
        # if image_id not in banned:
        #     queryset = queryset.filter(id=image_id)
        if id not in banned:
            queryset = queryset.filter(id=id)
        if experiment_name not in banned:
            # 1.根据实验名称获取实验环境id
            experiment_environment_queryset = Experiment.objects.filter(experiment_name__icontains=experiment_name)
            environment_ids = []
            for item in experiment_environment_queryset:
                environment_ids.append(item.environment_id)
            # 2.根据实验环境id集合获取到镜像id集合
            query_image = Environment.objects.get(id=1)
            environment_image_queryset = query_image.image.through.objects.all()
            image_ids = []
            for item in environment_image_queryset:
                if item.environment_id in environment_ids:
                    image_ids.append(item.image_id)
            image_queryset = set(image_ids)
            queryset = queryset.filter(id__in=image_queryset)
        # if experiment_name not in banned:
        #     queryset = queryset.filter(experiment_name__contains=experiment_name)
        # if str(image_type) in ['1','2','3']:
        #     queryset = queryset.filter(image_type=trans.image_type[str(image_type)])
        if str(image_type) in ['1', '2', '3']:
            queryset = queryset.filter(
                image_type='I' if image_type == '1' else 'V' if image_type == '2' else 'D')
        return queryset

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)


class TempInstanceListAPIView(mixins.ListModelMixin, viewsets.GenericViewSet):
    permission_classes = [pm.CustomIsAuthenticated, pm.AdminPermission|pm.TeacherPermission]
    serializer_class = TempInstancesSerializer
    model = serializer_class.Meta.model
    queryset = TempInstance.objects.all()

    def get_queryset(self):
        queryset = self.model.objects.filter(Q(user=self.request.user)) if self.request.user.user_type == 'T' else self.model.objects.all()
        queryset = queryset.filter(~Q(status='C')).order_by('-id')
        image_name = self.request.query_params.get('image_name', None)
        banned = ['',None]
        if image_name not in banned:
            queryset = queryset.filter(image_name__contains=image_name.strip())
        return queryset


class ImageCreateFirstView(APIView):

    permission_classes = [pm.CustomIsAuthenticated, pm.AdminPermission|pm.TeacherPermission]
    def __init__(self, **kwargs):
        self.response_format = CustomResponse().response
        self.message = ""
        super(ImageCreateFirstView, self).__init__(**kwargs)
    
    def get_object(self, obj_id):
        try:
            image = Image.objects.filter(id = obj_id).first()
            if self.request.user.user_type != 'A' and (image.owner not in [None, self.request.user]):
                return None
            return image
        except Image.DoesNotExist:
            return None

    def validate_ids(self, id_list):
        for id in id_list:
            Image.objects.get(id = id)
        return True

    def post(self, request, *args, **kwargs):
        try:
            image_id = GetPostParaOrNone(request.data, 'image_id')
            if image_id is None:
                raise Exception('镜像未选择')
            image = self.get_object(obj_id=image_id)
            if image is None:
                raise Exception('镜像不存在')
            image_name = GetPostParaOrNone(request.data, 'image_name', default=image.image_name).strip()
            one = TempInstance.objects.filter(image_name = image_name).first()
            imageName = Image.objects.filter(image_name = image_name).first()
            if one is not None:
                raise Exception('镜像名称已经存在,请重新取一个名称')
            if imageName is not None:
                raise Exception('镜像名称已经存在,请重新取一个名称/ToT/')
            ci = CloudImage(imageid=image.imageId)
            instanceid = ci.issue(image)
            if instanceid:
                instance = TempInstance()
                instance.instanceId = instanceid
                instance.image_name = image_name
                instance.image = image
                instance.user = request.user
                instance.save()
                self.message = '实例创建成功\n'
                whileCount = 0
                while 1:
                    print(whileCount)
                    if whileCount > 50:
                        raise Exception('实例开机失败')
                    try:
                        vncUrl = ci.DescribeInstanceVncUrl(instanceid)
                        self.response_format["data"] = {"instance_id":instance.id,"instanceid":instanceid,"vnc": vncUrl}
                        break
                    except Exception as e:
                        print(str(e))
                        whileCount += 1
                        time.sleep(5)
                    
            else:
                self.response_format["error_code"] = ErrorCode.parameter_error.value
                self.message = '实例创建失败\n'
        except Exception as e:
            traceback.print_exc()
            self.response_format["error_code"] = ErrorCode.parameter_error.value
            self.message = str(e)
        self.response_format["message"] = self.message
        return Response(self.response_format)

class ImageCreateSecondView(APIView):

    permission_classes = [pm.CustomIsAuthenticated, pm.AdminPermission|pm.TeacherPermission]
    def __init__(self, **kwargs):
        self.response_format = CustomResponse().response
        self.message = ""
        super(ImageCreateSecondView, self).__init__(**kwargs)
    
    def get_object(self, obj_id):
        try:
            return TempInstance.objects.get(Q(id = obj_id),Q(user=self.request.user))
        except TempInstance.DoesNotExist:
            return None

    def validate_ids(self, id_list):
        for id in id_list:
            TempInstance.objects.get(id = id)
        return True

    def post(self, request, *args, **kwargs):
        try:
            instance_id = GetPostParaOrNone(request.data, 'instance_id')
            if instance_id is None:
                raise Exception('参数错误')
            instance = self.get_object(obj_id=instance_id)
            if instance is None:
                raise Exception('实例不存在')
        
            # todo save instance as image
            print(instance.instanceId, instance.image_name)
            ci = CloudInstance()
            create_image = ci.createImage(instance.instanceId, instance.image_name, instance.image_name)
            # ci.recovery([instance.instanceId])
            print(create_image)
            with transaction.atomic():
                image_old = instance.image
                image_new = Image()
                image_new.image_name = instance.image_name
                image_new.image_type = image_old.image_type
                image_new.image_url = image_old.image_url
                image_new.imageId = create_image.ImageId
                image_new.import_status = 2
                image_new.opration_system = image_old.opration_system
                image_new.platform = image_old.platform
                image_new.version = image_old.version
                image_new.architecture = image_old.architecture
                image_new.owner = request.user
                image_new.save()
                instance.status = 'S'
                instance.save()
            self.message = "镜像制作完成"
        except  TencentCloudSDKException as e:
            traceback.print_exc()
            self.response_format["error_code"] = ErrorCode.comon_error.value
            self.message = str(e)
        except Exception as e:
            self.response_format["error_code"] = ErrorCode.parameter_error.value
            self.message = '实例关机失败\n'
        self.response_format["message"] = self.message
        return Response(self.response_format)

class ImageCreateThirdView(APIView):

    permission_classes = [pm.CustomIsAuthenticated, pm.AdminPermission|pm.TeacherPermission]
    def __init__(self, **kwargs):
        self.response_format = CustomResponse().response
        self.message = ""
        super(ImageCreateThirdView, self).__init__(**kwargs)
    
    def get_object(self, obj_id):
        try:
            return TempInstance.objects.get(Q(id = obj_id),Q(user=self.request.user))
        except TempInstance.DoesNotExist:
            return None

    def get_image(self, obj_id):
        try:
            image = Image.objects.filter(id = obj_id).first()
            if self.request.user.user_type != 'A' and (image.owner not in [None, self.request.user]):
                return None
            return image
        except Image.DoesNotExist:
            return None

    def validate_ids(self, id_list):
        for id in id_list:
            TempInstance.objects.get(id = id)
        return True

    def post(self, request, *args, **kwargs):
        try:
            instance_id = request.data['instance_id']
            image_name = request.data['image_name']
            image_id = request.data['image_id']
        except Exception as e:
            self.response_format["error_code"] = ErrorCode.parameter_error.value
            self.response_format["message"] = str(e) 
            return Response(self.response_format)
        try:
            instance = self.get_object(obj_id=instance_id)
            if instance is None:
                raise Exception('实例不存在')
            image_old = self.get_image(obj_id=image_id)
            if image_old is None:
                raise Exception('镜像不存在')
            image_new = Image()
            image_new.image_name = image_name
            image_new.image_type = image_old.image_type
            image_new.image_url = image_old.image_url
            image_new.imageId = image_old.imageId
            image_new.import_status = 2
            image_new.opration_system = image_old.opration_system
            image_new.platform = image_old.platform
            image_new.version = image_old.version
            image_new.architecture = image_old.architecture
            image_new.owner = request.user
            image_new.save()
            self.message = '镜像创建成功\n'
        except Exception as e:
            self.response_format["error_code"] = ErrorCode.parameter_error.value
            self.message = '镜像创建失败\n'
        self.response_format["message"] = self.message
        return Response(self.response_format)

class InstanceActionView(APIView):

    # permission_classes = [pm.CustomIsAuthenticated, pm.TeacherPermission]
    permission_classes = [pm.CustomIsAuthenticated, pm.TeacherPermission | pm.AdminPermission]
    def __init__(self, **kwargs):
        self.response_format = CustomResponse().response
        self.message = ""
        super(InstanceActionView, self).__init__(**kwargs)

    def post(self, request, *args, **kwargs):
        action = request.data['action']
        insId = GetPostParaOrNone(request.data, 'insId')
        user = request.user
        try:
            instance = TempInstance.objects.filter(id=insId).first()
            if (user.user_type == 'T'):
                instance = TempInstance.objects.filter(id=insId, user=user).first()
            # instance = TempInstance.objects.filter(id=insId, user=user).first()
            if action not in ['start', 'shutdown', 'recovery']:
                raise Exception('参数错误')
            if action == 'start': 
                ci = CloudInstance()
                ci.start([instance.instanceId])
                self.response_format["message"] =  '实例正在开机中，请您耐心等待'
            if action == 'shutdown':
                ci = CloudInstance()
                ci.shutdown([instance.instanceId])
                self.response_format["message"] =  '实例关机中，请您耐心等待'
            if action == 'recovery':
                ci = CloudInstance()
                ci.recovery([instance.instanceId])
                self.response_format["message"] =  '实例销毁中'
                with  transaction.atomic():
                    instance.status = 'C'
                    instance.save()
            return Response(self.response_format)
        except TempInstance.DoesNotExist:
            self.response_format['message'] = '实例不存在'
        except TencentCloudSDKException as e:
            self.response_format["error_code"] = ErrorCode.parameter_error.value
            self.response_format["message"] = str(e.message)
            return Response(self.response_format)
        except Exception as e: 
            traceback.print_exc()
            self.response_format["error_code"] = ErrorCode.parameter_error.value
            self.response_format["message"] = str(e)
            return Response(self.response_format)

class CancelInstance(APIView):

    queryset = TempInstance.objects.all()

    # permission_classes = [pm.CustomIsAuthenticated, pm.TeacherPermission]
    permission_classes = [pm.CustomIsAuthenticated, pm.TeacherPermission | pm.AdminPermission]
    def __init__(self, **kwargs):
        self.response_format = CustomResponse().response
        self.message = ""
        super(CancelInstance, self).__init__(**kwargs)

    def post(self, request, *args, **kwargs):
        insId = GetPostParaOrNone(request.data, 'insId')
        user = request.user
        try:
            instance = TempInstance.objects.filter(id=insId).first()
            if (user.user_type=='T'):
               instance = TempInstance.objects.filter(id=insId, user=user).first()
            with transaction.atomic():
                instance.status = 'C'    
                instance.save()
            self.response_format["message"] =  '实例回收成功'
            return Response(self.response_format)
        except TempInstance.DoesNotExist:
            self.response_format['message'] = '实例不存在'
        except Exception as e: 
            traceback.print_exc()
            self.response_format["error_code"] = ErrorCode.parameter_error.value
            self.response_format["message"] = str(e)
            return Response(self.response_format)

class DeleteMyImage(APIView):

    # permission_classes = [pm.CustomIsAuthenticated, pm.TeacherPermission]
    permission_classes = [pm.CustomIsAuthenticated, pm.TeacherPermission | pm.AdminPermission]
    def __init__(self, **kwargs):
        self.response_format = CustomResponse().response
        self.message = ""
        super(DeleteMyImage, self).__init__(**kwargs)

    def post(self, request, *args, **kwargs):
        id = GetPostParaOrNone(request.data, 'id')
        user = request.user
        logger.error("用户类型为{}".format(user.user_type))
        try:
            if (user.user_type=='T'):
                image = Image.objects.filter(id=id, owner=user).first()
            else:
                image = Image.objects.filter(id=id).first()
            ci = CloudInstance()
            cloudImage = CloudImage()
            imageBycloud = cloudImage.describeImagesByID(image.imageId)
            if imageBycloud is not None:
                ci.deleteImage(image.imageId)
            with  transaction.atomic():
                image.status = 'D'
                image.save()
            return Response(self.response_format)
        except Image.DoesNotExist:
            self.response_format['message'] = '镜像不存在'
        except TencentCloudSDKException as e:
            self.response_format["error_code"] = ErrorCode.parameter_error.value
            self.response_format["message"] = str(e.message)
            return Response(self.response_format)
        except Exception as e: 
            traceback.print_exc()
            self.response_format["error_code"] = ErrorCode.parameter_error.value
            self.response_format["message"] = str(e.message)
            return Response(self.response_format)


class AsyncImage(APIView):

    permission_classes = [pm.CustomIsAuthenticated]
    def __init__(self, **kwargs):
        self.response_format = CustomResponse().response
        self.message = ""
        super(AsyncImage, self).__init__(**kwargs)

    def post(self, request, *args, **kwargs):
        pagenation = 20
        offset = 0
        while 1:

            proxmox_list = proxmox_utils.get_template_list()
            for imageObj in proxmox_list:
                # image = Image.objects.filter(imageId=imageObj.ImageId).filter(owner=None).first()
                image = Image.objects.filter(imageId=imageObj.ImageId).first()
                if image is None:
                    image_new = Image()
                    image_new.image_name = imageObj.ImageName
                    image_new.image_type = 1
                    image_new.image_url = ''
                    image_new.imageId = imageObj.ImageId
                    image_new.import_status = 2
                    image_new.opration_system = imageObj.OsName
                    image_new.platform = imageObj.Platform
                    image_new.version = imageObj.OsName
                    image_new.architecture = imageObj.Architecture
                    image_new.save()
                else:
                    image.image_name = imageObj.ImageName
                    image.status = 'N'
                    image.save()
            if len(resp.ImageSet) < pagenation:
                break
            offset += pagenation
        self.response_format["message"] = "镜像同步成功"
        return Response(self.response_format)
    # def post(self, request, *args, **kwargs):
    #     pagenation = 20
    #     offset = 0
    #     while 1:
    #         req = models.DescribeImagesRequest()
    #         Filter = models.Filter()
    #         Filter.Name = 'image-type'
    #         Filter.Values = ['PRIVATE_IMAGE', 'SHARED_IMAGE']
    #         req.Filters = [Filter]
    #         req.Offset = offset
    #         req.Limit = pagenation
    #         resp = client.DescribeImages(req)
    #         for imageObj in resp.ImageSet:
    #             # image = Image.objects.filter(imageId=imageObj.ImageId).filter(owner=None).first()
    #             image = Image.objects.filter(imageId=imageObj.ImageId).first()
    #             if image is None:
    #                 image_new = Image()
    #                 image_new.image_name = imageObj.ImageName
    #                 image_new.image_type = 1
    #                 image_new.image_url = ''
    #                 image_new.imageId = imageObj.ImageId
    #                 image_new.import_status = 2
    #                 image_new.opration_system = imageObj.OsName
    #                 image_new.platform = imageObj.Platform
    #                 image_new.version = imageObj.OsName
    #                 image_new.architecture = imageObj.Architecture
    #                 image_new.save()
    #             else:
    #                 image.image_name = imageObj.ImageName
    #                 image.status = 'N'
    #                 image.save()
    #         if len(resp.ImageSet) < pagenation:
    #             break
    #         offset += pagenation
    #     self.response_format["message"] = "镜像同步成功"
    #     return Response(self.response_format)


